package com.zeng.stpro.modules.security.filter;

import com.alibaba.druid.util.StringUtils;
import com.google.code.kaptcha.Constants;
import com.zeng.stpro.commons.utils.Constant;
import com.zeng.stpro.modules.security.exception.CaptchaException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;

/**
 * @ClassName LoginCaptchaFilter 
 * @Description TODO
 * @Author zhijun zeng at 2020/3/13
 * @Version 1.0
 **/
public class LoginCaptchaFilter extends OncePerRequestFilter implements Filter {

    private String SESSION_KEY = Constant.CAPTCHA_KEY;
    private String login = "/api/admin/login";

    // 注入异常时处理 Handler
    private AuthenticationFailureHandler authenticationFailureHandler;

    public LoginCaptchaFilter(AuthenticationFailureHandler authenticationFailureHandler) {
        this.authenticationFailureHandler = authenticationFailureHandler;
    }


    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {

        //if(StringUtils.equals("/user/login", request.getRequestURI()) && StringUtils.equalsIgnoreCase(request.getMethod(), "post")) {
        if (StringUtils.equals(login, request.getRequestURI()) && StringUtils.equalsIgnoreCase(request.getMethod(), "POST")) {
            try {
                // 1. 进行验证码的校验
                validate(new ServletWebRequest(request));
            } catch (AuthenticationException e) {
                // 2. 捕获步骤1中校验出现异常，交给失败处理类进行进行处理
                authenticationFailureHandler.onAuthenticationFailure(request, response, e);
                return;
            }
        }

        // 继续 下一轮 Filter
        filterChain.doFilter(request, response);
    }

    /**
     *  VALIDATE 方法
     */
    private void validate(ServletWebRequest request) throws ServletRequestBindingException {
        // 1. 获取请求中的验证码
        String codeInRequest = ServletRequestUtils.getStringParameter(request.getRequest(), SESSION_KEY);

        // 2. 校验空值情况
        if(StringUtils.isEmpty(codeInRequest)) {
            throw new CaptchaException("验证码不能为空");
        }

        // 3. 获取服务器session池中的验证码
        String codeInSession = (String) request.getRequest().getSession().getAttribute(SESSION_KEY);
        if(Objects.isNull(codeInSession)) {
            throw new CaptchaException("验证码不存在");
        }

        // 4. 校验服务器session池中的验证码是否过期
        // 5. 请求验证码校验
        if(!StringUtils.equalsIgnoreCase(codeInSession, codeInRequest)) {
            throw new CaptchaException("验证码不匹配");
        }
    }


}
